package com.ddpt.platform.common.base;

import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.segments.NormalSegmentList;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ddpt.platform.common.base.session.AccessDataPermission;
import com.ddpt.platform.common.base.session.CurrentSessionUserPermission;
import com.ddpt.platform.common.constant.GlobalConstant;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class BizServiceImpl<M extends BizMapper<T>, T extends BizEntity> extends ServiceImpl<M, T> implements BizService<T> {

    @Override
    public <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {
        fillPermission(queryWrapper);
        long size = page.getSize();
        if(size < 0){
            List<T> list = list(queryWrapper);
            IPage<T> result = new Page<>();
            result.setRecords(list);
            result.setPages(1);
            result.setTotal(list==null?0:list.size());
            result.setCurrent(1);
            result.setSize(list==null?0:list.size());
            return (E) result;
        }
        return super.page(page, queryWrapper);
    }

    @Override
    public int count(Wrapper<T> queryWrapper) {
        fillPermission(queryWrapper);
        return super.count(queryWrapper);
    }

    @Override
    public List<T> listByIds(Collection<? extends Serializable> idList) {
        LambdaQueryWrapper<T> queryWrapper = Wrappers.lambdaQuery(this.entityClass).in(T::getId, idList);
        fillPermission(queryWrapper);
        return list(queryWrapper);
    }

    @Override
    public T get(T t) {
        return get(Wrappers.lambdaQuery(t));
    }

    @Override
    public boolean exists(T t) {
        return exists(Wrappers.lambdaQuery(t).select(BizEntity::getId));
    }

    @Override
    public boolean exists(Wrapper<T> queryWrapper) {
        if(queryWrapper instanceof LambdaQueryWrapper){
            LambdaQueryWrapper<T> lw = (LambdaQueryWrapper<T>) queryWrapper;
            lw.select(BizEntity::getId);
            lw.last("limit 1");
        }
        else if(queryWrapper instanceof QueryWrapper){
            QueryWrapper<T> qw = (QueryWrapper<T>) queryWrapper;
            qw.select("id");
            qw.last("limit 1");
        }
        return getOne(queryWrapper,false) != null;
    }

    @Override
    public T get(Wrapper<T> queryWrapper) {
        fillPermission(queryWrapper);
        if(AbstractWrapper.class.isAssignableFrom(queryWrapper.getClass())){
            AbstractWrapper aw = (AbstractWrapper) queryWrapper;
            aw.last("limit 1");
        }
        return getOne(queryWrapper,false);
    }

    @Override
    public List<T> list(T t) {
        LambdaQueryWrapper<T> queryWrapper = Wrappers.lambdaQuery(t);
        fillPermission(queryWrapper);
        return list(queryWrapper);
    }

    @Override
    public List<T> list() {
        LambdaQueryWrapper<T> queryWrapper = Wrappers.lambdaQuery(this.entityClass);
        return list(queryWrapper);
    }

    @Override
    public List<T> list(Wrapper<T> queryWrapper) {
        fillPermission(queryWrapper);
        return super.list(queryWrapper);
    }

    @Override
    public <E extends IPage<T>> E page(E page) {
        return page(page,Wrappers.lambdaQuery(this.entityClass));
    }

    @Override
    public <E extends IPage<T>> E page(E page, T t) {
        return page(page, Wrappers.lambdaQuery(t));
    }

    @Override
    public boolean deleteByIdsNotRemove(Collection<Long> idList) {
        if(idList==null || idList.isEmpty()){
            return true;
        }
        return update(Wrappers.<T>update().set("deleted",1).in("id",idList));
    }

    @Override
    public List<T> getBySplitIds(String ids) {
        if(StringUtils.isBlank(ids)){
            return null;
        }
        Set<Long> idSet = Stream.of(ids.split(",")).filter(StringUtils::isNotBlank).map(Long::valueOf).collect(Collectors.toSet());
        if(idSet.isEmpty()){
            return null;
        }
        return listByIds(idSet);
    }

    @Override
    public T getById(Serializable id) {
        return get(Wrappers.lambdaQuery(this.entityClass).eq(BizEntity::getId,id));
    }

    private void fillPermission(Wrapper<T> wrapper){
        if( 1 == 1 ){
            //暂时不要处理了，还是交给业务去处理
            return ;
        }
        AccessDataPermission dataPermission = CurrentSessionUserPermission.get();
        if(dataPermission == null){
            return ;
        }
        if(dataPermission.getAdminType().equals(GlobalConstant.ONE)){
            //超管放行
            return ;
        }
        if(!dataPermission.isEnabled()){
            return ;
        }
        if(!dataPermission.isManual()){
            dataPermission.setEnabled(false);
        }
        Class<T> clazz = this.entityClass;
        //当前查询条件实体类
        T entity = wrapper.getEntity();
        //按照权限拼接查询条件
        AccessDataPermission.DataPermissionType type = dataPermission.getType();
        if(type == AccessDataPermission.DataPermissionType.self){
            TableField tableField = ReflectUtil.getField(clazz, "createUserId").getDeclaredAnnotation(TableField.class);
            if(tableField==null || !tableField.exist()){
                return ;
            }
            if(entity!=null && entity.getCreateUserId() != null){
                return ;
            }
            //校验wrapper中是否拼接了create_user_id字段
            NormalSegmentList normal = wrapper.getExpression().getNormal();
            if(normal != null){
                for (ISqlSegment sqlSegment : normal) {
                    if("create_user_id".equalsIgnoreCase(sqlSegment.getSqlSegment())){
                        return ;
                    }
                }
            }
            if(dataPermission.getUserId() == null){
                return ;
            }
            if(wrapper instanceof LambdaQueryWrapper){
                LambdaQueryWrapper<T> lw = (LambdaQueryWrapper<T>) wrapper;
                lw.eq(BizEntity::getCreateUserId,dataPermission.getUserId());
            }
            if(wrapper instanceof QueryWrapper){
                QueryWrapper<T> qw = (QueryWrapper<T>) wrapper;
                qw.eq("create_user_id",dataPermission.getUserId());
            }
            return ;
        }
        TableField tableField = ReflectUtil.getField(clazz, "insId").getDeclaredAnnotation(TableField.class);
        if(tableField==null || !tableField.exist()){
            return ;
        }
        //判断当前条件中是否包含了机构条件
        if(entity!=null && entity.getInsId()!=null){
            return ;
        }
        //校验wrapper中是否拼接了ins字段
        NormalSegmentList normal = wrapper.getExpression().getNormal();
        if(normal != null){
            for (ISqlSegment sqlSegment : normal) {
                if("ins_id".equalsIgnoreCase(sqlSegment.getSqlSegment())){
                    return ;
                }
            }
        }
        if(CollectionUtils.isEmpty(dataPermission.getInsList())){
            return ;
        }
        if(wrapper instanceof LambdaQueryWrapper){
            LambdaQueryWrapper<T> lw = (LambdaQueryWrapper<T>) wrapper;
            lw.in(BizEntity::getInsId,dataPermission.getInsList());
        }
        if(wrapper instanceof QueryWrapper){
            QueryWrapper<T> qw = (QueryWrapper<T>) wrapper;
            qw.in("ins_id",dataPermission.getInsList());
        }
    }
}
